package com.yxy.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.yxy.common.PageResult;
import com.yxy.constant.MessageConstant;
import com.yxy.constant.StatusConstant;
import com.yxy.context.BaseContext;
import com.yxy.exception.*;
import com.yxy.mapper.UserMapper;
import com.yxy.pojo.dto.UserDTO;
import com.yxy.pojo.dto.UserLoginDTO;
import com.yxy.pojo.dto.UserPageQueryDTO;
import com.yxy.pojo.entity.User;
import com.yxy.pojo.vo.UserPageQueryVO;
import com.yxy.pojo.vo.UserVO;
import com.yxy.properties.AESProperties;
import com.yxy.service.UserService;
import com.yxy.utils.AESUtil;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AESProperties aesProperties;

    /**
     * 分页查询
     *
     * @param userPageQueryVO
     * @return
     */
    @Override
    public PageResult pageQuery(UserPageQueryDTO userPageQueryDTO) {
        PageHelper.startPage(userPageQueryDTO.getPage(), userPageQueryDTO.getPageSize());
        Page<UserPageQueryVO> page = userMapper.pageQuery(userPageQueryDTO);
        page.getResult().forEach(user -> {
            try {
                String password = AESUtil.decrypt(user.getPassword(), aesProperties.getSecretKey());
                user.setPassword(password);
            } catch (Exception e) {
                throw new ServerErrorException(MessageConstant.SERVER_ERROR);
            }
        });
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 新增
     *
     * @param userDTO
     */
    @SneakyThrows
    @Override
    public void add(UserDTO userDTO) {
        String username = userDTO.getUsername().trim();
        String password = userDTO.getPassword().trim();
        String phone = userDTO.getPhone().trim();
        // 判断登录名是否存在
        User u = userMapper.selectByUsername(username);
        if (u != null) {
            throw new AccountAlreadyExistsException(MessageConstant.ACCOUNT_ALREADY_EXISTS);
        }
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        user.setUsername(username);
        user.setPhone(userDTO.getPhone());
        // 密码加密
        user.setPassword(AESUtil.encrypt(password, aesProperties.getSecretKey()));
        user.setStatus(StatusConstant.ENABLE);
        // 若用户自己创建则性别默认的值为0，手动改为3设为保密状态
        if (user.getGender() == 0) {
            user.setGender(3);
        }
        // 用性别进行判断，管理端需要填入性别，用户端则不用，若性别为0则为用户本人注册，否则为管理员添加
        user.setCreateUser(user.getGender() != 0 && BaseContext.getCurrentId() != null ? BaseContext.getCurrentId() : -1);
        user.setCreateTime(LocalDateTime.now());
        userMapper.insert(user);
    }

    /**
     * 更新状态
     *
     * @param id
     * @param status
     */
    @Override
    public void updateStatus(int id, int status) {
        userMapper.updateStatus(id, status);
    }

    /**
     * 批量删除
     *
     * @param ids
     */
    @Override
    public void batchDelete(List<Integer> ids) {
        userMapper.deleteByIds(ids);
    }

    /**
     * 更新
     *
     * @param userDTO
     */
    @SneakyThrows
    @Override
    public void update(UserDTO userDTO) {
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        // 若用户自己修改信息，密码会单独进行修改，所以密码可能为空
        if (user.getPassword() != null) {
            user.setPassword(AESUtil.encrypt(user.getPassword(), aesProperties.getSecretKey()));
        }
        user.setUpdateUser(BaseContext.getCurrentId());
        user.setUpdateTime(LocalDateTime.now());
        userMapper.update(user);
    }

    /**
     * 登录
     *
     * @param userLoginDTO
     * @return
     */
    @SneakyThrows
    @Override
    public User login(UserLoginDTO userLoginDTO) {
        // 判断账号是否存在
        User user = userMapper.selectByUsername(userLoginDTO.getUsername());
        if (user == null) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        // 判断账号的状态是否可用
        if (user.getStatus() == StatusConstant.DISABLE) {
            throw new AccountNotAvailableException(MessageConstant.ACCOUNT_NOT_AVAILABLE);
        }
        // 密码进行加密，然后与数据库中的密码进行比对
        String password = AESUtil.encrypt(userLoginDTO.getPassword(), aesProperties.getSecretKey());
        if (!password.equals(user.getPassword())) {
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        return user;
    }

    /**
     * 根据id查询
     *
     * @param id
     * @return
     */
    @Override
    public UserVO getUserById(int id) {
        User user = userMapper.selectById(id);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    /**
     * 验证密码
     *
     * @param password
     * @return
     */
    @Override
    public Boolean verifyPwd(Integer userId, String password) {
        // 查询用户的密码
        User user = userMapper.selectById(userId);
        // 前端密码加密
        try {
            password = AESUtil.encrypt(password, aesProperties.getSecretKey());
        } catch (Exception e) {
            throw new ServerErrorException(MessageConstant.SERVER_ERROR);
        }
        // 密码比对
        if (!password.equals(user.getPassword())) {
            return false;
        }
        return true;
    }

    /**
     * 添加访客
     *
     * @param userId
     */
    @Transactional
    @Override
    public void addVisitor(int userId) {
        // 查询该用户原有的访问量
        User user = userMapper.selectById(userId);
        // 修改原有访问量
        userMapper.update(User.builder()
                .id(userId)
                .visitor(user.getVisitor() + 1)
                .build());
    }

    /**
     * 验证手机号
     *
     * @param username
     * @param phone
     * @return
     */
    @Override
    public Boolean verifyPhone(String username, String phone) {
        // 判断账号是否存在
        User user = userMapper.selectByUsername(username);
        if (user == null) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        // 判断手机号是否一致
        phone = phone.trim();
        if (!user.getPhone().equals(phone)) {
            throw new PhoneErrorException(MessageConstant.PHONE_ERROR);
        }
        return true;
    }

    /**
     * 重置密码
     *
     * @param userDTO
     */
    @Override
    public void resetPwd(UserDTO userDTO) {
        User user = new User();
        user.setUsername(userDTO.getUsername());
        String password = null;
        try {
            password = AESUtil.encrypt(userDTO.getPassword(), aesProperties.getSecretKey());
        } catch (Exception e) {
            throw new ServerErrorException(MessageConstant.SERVER_ERROR);
        }
        user.setPassword(password);
        userMapper.resetPwd(user);
    }
}
